home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
game.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-22
|
76KB
|
3,200 lines
/* game.c */
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#ifdef XENIX
#include <sys/signal.h>
#else
#include <signal.h>
#include <sys/wait.h>
#endif /* xenix */
#include <sys/time.h>
#include <sys/types.h>
#include "config.h"
#include "db.h"
#include "game.h"
#include "externs.h"
#include "interface.h"
#include "match.h"
#include "globals.h"
#ifdef HAS_RUSAGE
#include <sys/resource.h>
#endif
#ifdef MEM_CHECK
#include "mem_check.h"
#endif
/* declarations */
char dumpfile[200];
static time_t start_time; /* MUSH start time */
static int epoch = 0;
int reserved;
int depth = 0; /* excessive recursion prevention */
extern int invok_counter; /* function recursion prevention */
extern dbref cplr;
extern char ccom[];
extern char rptr[10][BUFFER_LEN]; /* from eval.c */
static int paranoid_dump = 0; /* if paranoid, scan before dumping */
int paranoid_checkpt = 0; /* write out an okay message every x objs */
void fork_and_dump();
void dump_database();
#ifdef DBSTATS_ENABLED
extern void do_dbstats();
#endif
extern dbref first_free; /* head of free object list, destroy.c */
dbref speaker = NOTHING;
/*
* used to allocate storage for temporary stuff, cleared before command
* execution
*/
void do_dump(player, num, flag)
dbref player;
char *num;
int flag;
{
/* if flag is 0, do a normal dump. otherwise, do a paranoid dump */
time_t tt;
if (Wizard(player)) {
if (options.daytime) {
notify(player, "Sorry, CPU intensive commands are currently disabled.");
return;
}
tt = time((time_t *) 0);
if (flag) {
/* want to do a scan before dumping each object */
paranoid_dump = 1;
if (num && *num) {
/* checkpoint interval given */
paranoid_checkpt = atoi(num);
if ((paranoid_checkpt < 1) || (paranoid_checkpt >= db_top)) {
notify(player, "Permission denied. Invalid checkpoint interval.");
paranoid_dump = 0;
return;
}
} else {
/* use a default interval */
paranoid_checkpt = db_top / 5;
if (paranoid_checkpt < 1)
paranoid_checkpt = 1;
}
notify(player, tprintf("Paranoid dumping, checkpoint interval %d.",
paranoid_checkpt));
fprintf(checklog_fp,
"*** PARANOID DUMP *** done by %s(#%d),\n",
db[player].name, player);
fprintf(checklog_fp, "\tcheckpoint interval %d, at %s",
paranoid_checkpt, ctime(&tt));
} else {
/* normal dump */
paranoid_dump = 0; /* just to be safe */
notify(player, "Dumping...");
fprintf(checklog_fp, "** DUMP ** done by %s(#%d) at %s",
db[player].name, player, ctime(&tt));
}
fflush(checklog_fp);
fork_and_dump();
paranoid_dump = 0;
} else {
notify(player, "Sorry, you are in a no dumping zone.");
}
}
/* print out stuff into error file */
void report()
{
#ifdef REPORT_TRACES
fprintf(tracelog_fp, "****REPORT TRACE!****\n\tCommand:%s\tdepth:%d\n", ccom,
depth);
fflush(tracelog_fp);
if ((cplr > 0) && (cplr <= db_top))
fprintf(tracelog_fp, "\tPlayer #%d\n\tlocation #%d\n", cplr,
db[cplr].location);
#else
fprintf(tracelog_fp, "TRACE: Cmd %s, depth %d", ccom, depth);
if (GoodObject(cplr))
fprintf(tracelog_fp, ", from #%d at #%d\n", cplr, Location(cplr));
else
fprintf(tracelog_fp, "\n");
#endif /* REPORT_TRACES */
fflush(tracelog_fp);
}
#ifdef DESTROY
void do_purge(player)
dbref player;
{
if (Wizard(player)) {
FIX;
notify(player, "Purge complete.");
} else
notify(player, "Sorry, you are a mortal.");
}
void dest_info(thing, tt)
dbref thing;
dbref tt;
{
if (thing == NOTHING && !Floating(tt)) {
if (db[tt].name) {
notify(db[tt].owner, tprintf("You own a disconnected room, %s(#%d)",
db[tt].name, tt));
} else
do_log(LT_ERR, NOTHING, NOTHING, "ERROR: no name for room #%d.", tt);
return;
}
/* hopefully this check will remove some odd messages when things for
* some reason get marked wrong? Just a guess. Ick.
*/
if (thing == NOTHING)
return;
switch (Typeof(thing)) {
case TYPE_ROOM: /* Tell all players room has gone away */
notify_except(db[thing].contents, 0,
"The floor disappears under your feet, you fall through NOTHINGness and then:");
break;
case TYPE_PLAYER: /* Show them where they arrived */
enter_room(thing, HOME);
break;
}
}
#endif /* DESTROY */
void notify_check(player, msg, no_puppet)
dbref player;
const char *msg;
int no_puppet;
{
/* we only echo puppet messages if the puppet is in a different room
* from its owner, or we're explicitly told that puppet echo is okay.
*/
ATTR *d;
char tbuf1[BUFFER_LEN];
char *bp, *inpref;
if ((player < 0) || (player >= db_top))
return;
if (depth++ > 7) {
depth--;
return;
}
switch (Typeof(player)) {
case TYPE_ROOM:
case TYPE_EXIT:
depth--;
return;
break; /* NOTREACHED */
case TYPE_PLAYER:
raw_notify(player, msg);
#ifndef PLAYER_LISTEN
depth--;
return;
#endif /* PLAYER_LISTEN */
break;
case TYPE_THING:
if ((Toggles(player) & THING_PUPPET) &&
(!no_puppet || (Location(player) != Location(Owner(player))))) {
bp = tbuf1;
safe_str(Name(player), tbuf1, &bp);
safe_chr('>', tbuf1, &bp);
safe_chr(' ', tbuf1, &bp);
safe_str(msg, tbuf1, &bp);
*bp = '\0';
raw_notify(db[player].owner, tbuf1);
}
}
/* do @listen stuff */
d = atr_get_noparent(player, "LISTEN");
if (d) {
strcpy(tbuf1, uncompress(d->value));
if(wild_match(tbuf1, msg)) {
if (speaker != player)
did_it(speaker,player, 0, NULL, 0, NULL, "AHEAR", NOTHING);
else
did_it(speaker, player, 0, NULL, 0, NULL, "AMHEAR", NOTHING);
did_it(speaker, player, 0, NULL, 0, NULL, "AAHEAR", NOTHING);
/* also pass the message on
* Note: not telling player protects against two forms
* of recursion:
* player doesn't tell itself (as container) or as contents
* using teleport it is possible to create a recursive loop
* but this will be terminated when the depth variable exceeds 30
*/
if (!member(speaker, db[player].contents) &&
!filter_found(player, msg, 1)) {
d = atr_get(player, "INPREFIX");
if (d) {
strcpy(tbuf1, uncompress(d->value));
inpref = exec(player, speaker,
EV_STRIP | EV_FCHECK, tbuf1);
bp = tbuf1;
safe_str(inpref, tbuf1, &bp);
safe_chr(' ', tbuf1, &bp);
safe_str(msg, tbuf1, &bp);
*bp = '\0';
free(inpref);
}
if (IS(player, TYPE_THING, THING_PUPPET))
notify_except2(db[player].contents, player, Owner(player),
(d) ? tbuf1 : msg);
else
notify_except(db[player].contents, player,
(d) ? tbuf1 : msg);
}
}
}
/* if object is flagged LISTENER, check for ^ listen patterns
* these are like AHEAR - object cannot trigger itself.
* unlike normal @listen, don't pass the message on.
*/
if ((speaker != player) && (IS(player, TYPE_THING, THING_LISTEN)))
atr_comm_match(player, speaker, '^', ':', msg, 0);
depth--;
}
#ifdef HAS_RUSAGE
void rusage_stats()
{
struct rusage usage;
int pid, psize;
pid = getpid();
psize = getpagesize();
getrusage(RUSAGE_SELF, &usage);
fprintf(stderr, "\nProcess statistics:\n");
fprintf(stderr, "Time used: %10d user %10d sys\n",
usage.ru_utime.tv_sec, usage.ru_stime.tv_sec);
fprintf(stderr, "Max res mem: %10d pages %10d bytes\n",
usage.ru_maxrss, (usage.ru_maxrss * psize));
fprintf(stderr, "Integral mem:%10d shared %10d private %10d stack\n",
usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss);
fprintf(stderr, "Page faults: %10d hard %10d soft %10d swapouts\n",
usage.ru_majflt, usage.ru_minflt, usage.ru_nswap);
fprintf(stderr, "Disk I/O: %10d reads %10d writes\n",
usage.ru_inblock, usage.ru_oublock);
fprintf(stderr, "Network I/O: %10d in %10d out\n",
usage.ru_msgrcv, usage.ru_msgsnd);
fprintf(stderr, "Context swi: %10d vol %10d forced\n",
usage.ru_nvcsw, usage.ru_nivcsw);
fprintf(stderr, "Signals: %10d\n", usage.ru_nsignals);
}
#endif /* HAS_RUSAGE */
void do_shutdown(player)
dbref player;
{
if (Wizard(player)) {
raw_broadcast(0, "GAME: Shutdown by %s", db[player].name);
do_log(LT_ERR, player, NOTHING, "SHUTDOWN by %s\n",
unparse_object(player, player));
/* This will create a file used to check if a restart should occur */
#ifdef AUTORESTART
system("touch NORESTART");
#endif
shutdown_flag = 1;
} else {
notify(player, "Your delusions of grandeur have been duly noted.");
}
}
#ifdef XENIX
/* rename hack!!! */
rename(s1, s2)
char *s1;
char *s2;
{
char buff[300];
sprintf(buff, "mv %s %s", s1, s2);
system(buff);
}
#endif
static void dump_database_internal()
{
char tmpfl[2048];
FILE *f;
extern int unlink();
sprintf(tmpfl, "%s.#%d#", dumpfile, epoch - 1);
unlink(tmpfl); /* nuke our predecessor */
sprintf(tmpfl, "%s.#%d#", dumpfile, epoch);
#ifdef DBCOMP
if ((f = popen(tprintf("%s >%s", options.compress, tmpfl), "w")) != NULL) {
if (paranoid_dump)
db_paranoid_write(f);
else
db_write(f);
pclose(f);
if (rename(tmpfl, dumpfile) < 0)
perror(tmpfl);
} else
perror(tmpfl);
#ifdef USE_MAILER
sprintf(tmpfl, "%s.#%d#", options.mail_db, epoch - 1);
unlink(tmpfl);
sprintf(tmpfl, "%s.#%d#", options.mail_db, epoch);
if (mdb_top >= 0)
if ((f =
popen(tprintf("%s >%s", options.compress, tmpfl), "w")) != NULL) {
dump_mail(f);
pclose(f);
if (rename(tmpfl, options.mail_db) < 0)
perror(tmpfl);
} else
perror(tmpfl);
#endif /* USE_MAILER */
#ifdef ALLOW_RPAGE
sprintf(tmpfl, "rpage.db.Z.#%d#", epoch - 1);
unlink(tmpfl);
sprintf(tmpfl, "rpage.db.Z.#%d#", epoch);
if ((f = popen(tprintf("%s >%s", options.compress, tmpfl), "w")) != NULL) {
dump_server_database(f);
pclose(f);
if (rename(tmpfl, "rpage.db.Z") < 0)
perror(tmpfl);
} else
perror(tmpfl);
#endif /* ALLOW_RPAGE */
#else /* DBCOMP */
if ((f = fopen(tmpfl, "w")) != NULL) {
if (paranoid_dump)
db_paranoid_write(f);
else
db_write(f);
fclose(f);
if (rename(tmpfl, dumpfile) < 0)
perror(tmpfl);
} else
perror(tmpfl);
#ifdef USE_MAILER
sprintf(tmpfl, "%s.#%d#", options.mail_db, epoch - 1);
unlink(tmpfl);
sprintf(tmpfl, "%s.#%d#", options.mail_db, epoch);
if ((f = fopen(tmpfl, "w")) != NULL) {
dump_mail(f);
fclose(f);
if (rename(tmpfl, options.mail_db) < 0)
perror(tmpfl);
} else
perror(tmpfl);
#endif /* USE_MAILER */
#ifdef ALLOW_RPAGE
sprintf(tmpfl, "rpage.db.#%d#", epoch - 1);
unlink(tmpfl);
sprintf(tmpfl, "rpage.db.#%d#", epoch);
if ((f = fopen(tmpfl, "w")) != NULL) {
dump_server_database(f);
fclose(f);
if (rename(tmpfl, "rpage.db") < 0)
perror(tmpfl);
} else
perror(tmpfl);
#endif /* ALLOW_RPAGE */
#endif /* DB_COMP */
}
void panic(message)
const char *message;
{
const char *panicfile = options.crash_db;
FILE *f;
int i;
fprintf(stderr, "PANIC: %s\n", message);
report();
raw_broadcast(0, "EMERGENCY SHUTDOWN: %s", message);
/* turn off signals */
for (i = 0; i < NSIG; i++) {
signal(i, SIG_IGN);
}
/* shut down interface */
emergency_shutdown();
/* dump panic file */
if ((f = fopen(panicfile, "w")) == NULL) {
perror("CANNOT OPEN PANIC FILE, YOU LOSE");
_exit(135);
} else {
fprintf(stderr, "DUMPING: %s\n", panicfile);
db_write(f);
fclose(f);
fprintf(stderr, "DUMPING: %s (done)\n", panicfile);
_exit(136);
}
}
void dump_database()
{
epoch++;
fprintf(stderr, "DUMPING: %s.#%d#\n", dumpfile, epoch);
dump_database_internal();
fprintf(stderr, "DUMPING: %s.#%d# (done)\n", dumpfile, epoch);
}
static int reaper()
{
union wait my_stat;
while (wait3(&my_stat, WNOHANG, 0) > 0)
;
signal(SIGCLD, (void *)reaper);
}
void fork_and_dump()
{
int child;
epoch++;
fprintf(checklog_fp, "CHECKPOINTING: %s.#%d#\n", dumpfile, epoch);
fflush(checklog_fp);
#ifndef NO_FORK
#ifdef USE_VFORK
raw_broadcast(0, DUMP_NOFORK_MESSAGE);
child = vfork();
#else /* USE_VFORK */
child = fork();
#endif /* USE_VFORK */
#else /* NO FORK */
raw_broadcast(0, DUMP_NOFORK_MESSAGE);
child = 0;
#endif /* NO_FORK */
if (child == 0) {
/* in the child */
close(reserved); /* get that file descriptor back */
#ifdef CONCENTRATOR
#ifndef XENIX
signal(SIGCHLD, SIG_DFL);
#else
signal(SIGCLD, SIG_DFL);
#endif /* XENIX */
#endif /* CONCENTRATOR */
dump_database_internal();
#ifndef NO_FORK
_exit(0); /* !!! */
#else /* NO FORK */
reserved = open("/dev/null", O_RDWR);
#ifdef CONCENTRATOR
#ifndef XENIX
signal(SIGCHLD, (void *) reaper);
#else
signal(SIGCLD, (void *) reaper);
#endif /* XENIX */
#endif /* CONCENTRATOR */
#endif /* NO_FORK */
} else if (child < 0) {
perror("fork_and_dump: fork()");
}
}
void do_restart()
{
dbref thing;
ATTR *s;
char *r;
char buf[SBUF_LEN];
/* Do stuff that needs to be done for players only: add stuff to the
* alias table, and refund money from queued commands at shutdown.
*/
for (thing = 0; thing < db_top; thing++) {
if (Typeof(thing) == TYPE_PLAYER) {
if ((s = atr_get_noparent(thing, "ALIAS")) != NULL) {
strcpy(buf, uncompress(s->value));
add_player(thing, buf);
}
if ((s = atr_get_noparent(thing, "QUEUE")) != NULL) {
giveto(thing, QUEUE_COST * atoi(uncompress(s->value)));
atr_add(thing, "QUEUE", "", GOD, NOTHING);
}
}
}
/* Once we load all that, then we can trigger the startups and
* begin queueing commands. Also, let's make sure that we get
* rid of null names.
*/
for (thing = 0; thing < db_top; thing++) {
if (Name(thing) == NULL) {
do_log(LT_ERR, NOTHING, NOTHING, "Null name on object #%d",
thing);
if (Going(thing))
SET(Name(thing), "Garbage");
else
SET(Name(thing), "XXXX");
}
if (!Going(thing) &&
(Flags(thing) & STARTUP) && !(Flags(thing) & HALT)) {
s = atr_get_noparent(thing, "STARTUP");
if (!s)
continue; /* just in case */
r = safe_uncompress(s->value);
parse_que(thing, r, thing);
free(r);
}
}
}
int init_game(conf)
const char *conf;
{
FILE *f;
int a;
extern void init_timer();
extern void config_file_startup();
const char *infile, *outfile;
#ifdef USE_MAILER
const char *mailfile;
#endif
depth = 0;
for (a = 0; a < 10; a++)
wptr[a] = NULL;
/* set MUSH start time */
start_time = time((time_t *) 0);
fprintf(stderr, "MUSH restarted, PID %d, at %s\n",
getpid(), ctime(&start_time));
/* initialize all the hash tables: flags, functions, and attributes. */
init_flag_hashtab();
init_func_hashtab();
init_aname_hashtab();
config_file_startup(conf);
infile = options.input_db;
outfile = options.output_db;
#ifdef USE_MAILER
mailfile = options.mail_db;
#endif
/* read small text files into cache */
fcache_init();
#ifdef DBCOMP
if ((f =
popen(tprintf("%s < %s", options.uncompress, infile), "r")) == NULL)
return -1;
#else
if ((f = fopen(infile, "r")) == NULL)
return -1;
#endif
/* ok, read it in */
fprintf(stderr, "LOADING: %s\n", infile);
if (db_read(f) < 0) {
fprintf(stderr, "ERROR LOADING\n");
return -1;
}
fprintf(stderr, "LOADING: %s (done)\n", infile);
/* everything ok */
#ifdef DBCOMP
pclose(f);
#else
fclose(f);
#endif
/* complain about bad config options */
if (!GoodObject(PLAYER_START) || (Typeof(PLAYER_START) != TYPE_ROOM))
fprintf(stderr, "WARNING: Player_start (#%d) is NOT a room.\n",
PLAYER_START);
#ifdef DO_GLOBALS
if (!GoodObject(MASTER_ROOM) || (Typeof(MASTER_ROOM) != TYPE_ROOM))
fprintf(stderr, "WARNING: Master room (#%d) is NOT a room.\n",
MASTER_ROOM);
#endif /* DO_GLOBALS */
#ifdef GUEST_RESTRICT
if (!GoodObject(GUEST_PLAYER) || (Typeof(GUEST_PLAYER) != TYPE_PLAYER))
fprintf(stderr, "WARNING: Guest player (#%d) is NOT a player.\n",
GUEST_PLAYER);
#endif /* GUEST_RESTRICT */
#ifdef USE_MAILER
/* read mail database */
#ifdef DBCOMP
f = popen(tprintf("%s < %s", options.uncompress, mailfile), "r");
if (f == NULL)
mail_init();
#else /* DBCOMP */
f = fopen(mailfile, "r");
if (f == NULL)
mail_init();
#endif /* DBCOMP */
/* okay, read it in */
else {
fprintf(stderr, "LOADING: %s\n", mailfile);
load_mail(f);
fprintf(stderr, "LOADING: %s (done)\n", mailfile);
#ifdef DBCOMP
pclose(f);
#else /* DBCOMP */
fclose(f);
#endif /* DBCOMP */
}
#endif /* USE_MAILER */
#ifdef ADD_NO_COMMAND_FLAG
/* futz with the database to add the new NO_COMMAND flag.
* By default, it's probably best to set this on rooms and players,
* since they get checked for $commands a lot but rarely get a match.
* Individual players can unset the flag manually if they need to
* match commands.
*/
for (a = 0; a < db_top; a++) {
if ((Typeof(a) == TYPE_ROOM) || (Typeof(a) == TYPE_PLAYER))
db[a].flags |= NO_COMMAND;
}
#endif
/* set up the chat system table */
#if (CHAT_SYSTEM >= 2)
init_chat();
#endif /* CHAT_SYSTEM */
/* now do the rpage stuff */
#ifdef ALLOW_RPAGE
rpage_init();
#endif /* ALLOW_RPAGE */
/* initialize random number generator */
srandom(getpid());
/* set up dumper */
strcpy(dumpfile, outfile);
init_timer();
#ifndef XENIX
signal(SIGCHLD, (void *)reaper);
#else /* xenix */
signal(SIGCLD, (void *)reaper);
#endif
/* everything else ok. Restart all objects. */
do_restart();
return 0;
}
static void do_readcache(player)
dbref player;
{
if (!Wizard(player)) {
notify(player, "Permission denied.");
return;
}
fcache_load(player);
}
#if (CHAT_SYSTEM >= 2)
static int parse_chat(player, command)
dbref player;
char *command;
{
/* function hacks up something of the form "+<channel> <message",
* finding the two args, and passes it to do_chat
*/
char *arg1;
char *arg2;
char tbuf1[MAX_COMMAND_LEN];
char *s;
channel_type chan;
strcpy(tbuf1, command); /* don't hack it up */
s = tbuf1;
arg1 = s;
while (*s && !isspace(*s))
s++;
if (*s) {
*s++ = '\0';
while (*s && isspace(*s))
s++;
}
arg2 = s;
chan = find_channel(arg1);
if (!chan) /* not valid channel, go parse command */
return 0;
else {
do_chat(player, chan, arg2);
return 1;
}
}
#endif /* CHAT_SYSTEM */
static void set_interp(player, cause, obj, attrib, val, from_port)
dbref player;
dbref cause;
char *obj;
char *attrib;
char *val;
int from_port;
{
/* Set of the format &attr, @attr, or @_attr.
* We need to know if something was directly typed in so we don't
* put it through our interpreter.
*/
char tbuf1[BUFFER_LEN];
char *name = NULL;
char *ptr = NULL;
int need_free = 0;
char *bp;
name = exec(player, cause, EV_STRIP | EV_FCHECK, obj);
if (*val) {
if (from_port) {
/* just strip off a layer of braces and don't interpret */
ptr = parse_to(&val, '\0', 0);
} else {
ptr = exec(player, cause, EV_STRIP | EV_FCHECK, val);
need_free = 1;
}
} else {
ptr = val;
}
bp = tbuf1;
safe_str(attrib, tbuf1, &bp);
safe_chr(':', tbuf1, &bp);
safe_str(ptr, tbuf1, &bp);
*bp = '\0';
do_set(player, name, tbuf1);
if (name)
free(name);
if (need_free) {
free(ptr);
#ifdef MEM_CHECK
del_check("exec.buff");
#endif
}
}
int test_set(player, cause, command, arg1, arg2, from_port)
dbref player;
dbref cause;
char *command;
char *arg1;
char *arg2;
int from_port;
{
/* check for an attribute set using @attr or &attr */
ATTR *atrp;
char *atrname = NULL;
if (command[0] != '@' && command[0] != '&')
return (0);
/* added to make this 2.0 compatible. with '&' equivalent to '@_' */
if ((command[0] == '&') && (command[1] != '\0')) {
atrname = exec(player, cause, EV_EVAL | EV_FCHECK, command + 1);
set_interp(player, cause, arg1, atrname, arg2, from_port);
if (atrname)
free(atrname);
return (1);
}
/* first character is '@' */
/* check if it's a regular attribute */
atrp = atr_match(strupper(command + 1));
if (atrp != NULL) {
set_interp(player, cause, arg1, atrp->name, arg2, from_port);
return (1);
}
/* else treat it as a user-defined one */
if((command[1] != '_') || (command[2] == '\0'))
return (0);
atrname = exec(player, cause, EV_EVAL | EV_FCHECK, command + 1);
set_interp(player, cause, arg1, command + 2, arg2, from_port);
if (atrname)
free(atrname);
return (1);
}
char **argv_hack(player, cause, arg, fargs, eflags)
dbref player;
dbref cause;
char *arg;
char *fargs[];
int eflags;
{
char *xargs[MAX_ARG];
int i;
if (!arg || !*arg) { /* make sure there's something to parse */
for (i = 0; i < MAX_ARG; i++)
fargs[i] = NULL;
return fargs;
}
parse_arglist(player, cause, arg, '\0', eflags, xargs, MAX_ARG);
/* because somebody braindamaged decided, way back when, that
* argv command lists were going to start at argv[1], we have
* to do a thoroughly inelegant copy.
*/
for (i = 0; i < MAX_ARG - 1; i++) {
fargs[i + 1] = xargs[i];
}
if (xargs[MAX_ARG - 1]) { /* extra we can't use */
free(xargs[MAX_ARG - 1]);
#ifdef MEM_CHECK
del_check("exec.buff");
#endif
}
return fargs;
}
/*
* use this only in process_command
*/
#define Matched(string) { if(!string_prefix((string), command)) goto bad; }
#define IfSwitch(string) if (string_prefix((string), slashp))
#define arg1 buf1 = exec(player, cause, EV_STRIP | EV_FCHECK, buf2)
#define arg2 saveptr = exec(player, cause, EV_STRIP | EV_FCHECK, arg)
#define argu saveptr = exec(player, cause, EV_STRIP | EV_FCHECK, buff3)
#define argv argv_hack(player, cause, arg, fargs, EV_EVAL | EV_STRIP)
#define vargs argv_hack(player, cause, arg, fargs, EV_STRIP)
#define list_match(x) list_check(x, player, '$', ':', cptr, 0)
#define cmd_match(x) atr_comm_match(x, player, '$', ':', cptr, 0);
void process_command(player, command, cause, from_port)
dbref player;
char *command;
dbref cause;
int from_port; /* 1 if this is direct input from a port
* (i.e. typed directly by a player).
* attrib sets don't get parsed then.
*/
{
int a;
char *q; /* utility */
char *p; /* utility */
char *fargs[MAX_ARG];
char buff3[BUFFER_LEN];
char unp[BUFFER_LEN]; /* unparsed command */
/* general form command arg0=arg1,arg2...arg10 */
int gagged = 0;
char temp[BUFFER_LEN]; /* utility */
int i; /* utility */
char *slashp = NULL;
char tchar;
char *buf1 = NULL;
char *buf2 = NULL;
char *arg = NULL;
char *saveptr = NULL;
char *cptr = NULL;
void do_poor();
void do_version(), do_dolist(), do_config(), do_uptime(), do_scan();
for (a = 0; a < MAX_ARG; a++)
fargs[a] = NULL;
depth = 0;
if (command == 0) {
do_log(LT_ERR, NOTHING, NOTHING, "ERROR: No command!!!");
return;
}
#ifdef NEVER
/* Why was this being done??? It makes no sense. */
#ifndef HPUX
/* just to have fun, let's reinit the random number gen (with the time) */
srandom((int)time((time_t *) 0));
#endif /* HPUX */
#endif /* NEVER */
/* This check removed because it's a little extreme. For example,
* someone looking at God ought to be able to trigger his @adesc.
if (God(player) && !God(cause))
return;
*/
/* robustify player */
if ((player < 0) || (player >= db_top)) {
fprintf(stderr, "ERROR: bad player %d in process_command\n", player);
return;
}
gagged = IS(db[player].owner, TYPE_PLAYER, PLAYER_GAGGED);
/* Access the player */
Access(player);
/* Halted or destroyed objects can't execute commands */
if ((Typeof(player) != TYPE_PLAYER) &&
((Flags(player) & GOING) || (Flags(player) & HALT))) {
notify(Owner(player),
tprintf("Attempt to execute command by halted object #%d",
player));
return;
}
/* Players and things should not have invalid locations. This check
* must be done _after_ the destroyed-object check.
*/
if ((!GoodObject(Location(player)) ||
((Flags(Location(player)) & GOING) &&
(Typeof(Location(player)) != TYPE_ROOM))) && Mobile(player)) {
notify(Owner(player),
tprintf("Invalid location on command execution: %s(#%d)",
Name(player), player));
do_log(LT_ERR, NOTHING, NOTHING,
"Command attempted by %s(#%d) in invalid location #%d.",
Name(player), player, Location(player));
moveto(player, PLAYER_START); /* move it someplace valid */
}
/* The following check is removed due to a security hole it causes!
* 'If player is an exit or room execute command as owner'
*/
/* if ((Typeof(player) == TYPE_ROOM) || (Typeof(player) == TYPE_EXIT))
player = db[player].owner; */
speaker = player;
if (options.log_commands || Suspect(player))
do_log(LT_CMD, player, 0, "%s", command);
if (Flags(player) & VERBOSE)
raw_notify(Owner(player), tprintf("#%d] %s", player, command));
/* clear our local registers */
for (a = 0; a < 10; a++)
*(rptr[a]) = '\0';
/* reset the function invocation counter */
invok_counter = 0;
/* eat leading whitespace */
while (*command && isspace(*command))
command++;
/* eat extra white space */
q = p = command;
while (*p) {
/* scan over word */
while (*p && !isspace(*p))
*q++ = *p++;
/* smash spaces */
while (*p && isspace(*++p)) ;
if (*p)
*q++ = ' '; /* add a space to separate next word */
}
/* terminate */
*q = '\0';
/* ignore null commands that aren't from players */
if ((!command || !*command) && !from_port)
return;
/* important home checking comes first! */
if (strcmp(command, "home") == 0) {
if(Typeof(player) == TYPE_EXIT || Typeof(player) == TYPE_ROOM)
return;
do_move(player, command, 0);
return;
}
/* check for forces of the format: "#100 :do this." */
if (!gagged && Mobile(player) && (*command == '#') &&
force_by_number(player, command))
return;
/* check for single-character commands */
if (*command == SAY_TOKEN && !gagged) {
buf1 = exec(player, cause, EV_STRIP | EV_FCHECK, command + 1);
do_say(player, buf1);
} else if (*command == POSE_TOKEN && !gagged) {
buf1 = exec(player, cause, EV_STRIP | EV_FCHECK, command + 1);
do_pose(player, buf1, 0);
} else if (*command == SEMI_POSE_TOKEN && !gagged) {
buf1 = exec(player, cause, EV_STRIP | EV_FCHECK, command + 1);
do_pose(player, buf1, 1);
#if (CHAT_SYSTEM >= 2)
} else if (*command == CHAT_TOKEN && !gagged &&
parse_chat(player, command + 1)) {
/* the parse_chat function will take care of doing the chat messages
* if a channel is found. Otherwise, we want to go on.
*/
return;
#endif /* CHAT_SYSTEM */
/* now check if command is an exact match for an exit in the room */
} else if (can_move(player, command)) {
if (!Mobile(player))
return;
do_move(player, command, 0);
} else {
strcpy(unp, command);
/* parse arguments */
/* split command from arguments */
/* move over command word */
for (arg = command; *arg && !isspace(*arg); arg++)
;
/* truncate command */
if (*arg)
*arg++ = '\0';
/* grab switches and strip them off, truncating command, unless
* the first character of the command is a '&'. That indicates
* an attribute set; in order to avoid clobbering functions
* like 'get' which use a slash (and because we can't give
* switches to an &-attribute set anyway), we don't grab switches.
*/
if (*command != '&') {
slashp = (char *) index(command, '/');
if (slashp)
*slashp++ = '\0';
}
/* move over spaces */
while (*arg && isspace(*arg))
arg++;
strcpy(buff3, arg); /* save it for news */
buf2 = parse_to(&arg, '=', 0);
/* Don't choke when no '=' was specified */
if (!arg || (arg && !*arg)) {
arg = &tchar;
*arg = '\0';
}
if (!gagged && test_set(player, cause, command, buf2, arg, from_port)) {
/* we don't need to free any memory. It's been done for us. */
return;
}
/* Just as a reminder of what all these variables mean:
*
* arg1, arg2, argu, and argv are all macros. They evaluate to
* pronoun-substituted versions of the left hand side of the = sign,
* right hand side of the = sign, the full expression regardless of
* = sign, and the parsed version of an argument list.
* vargs is a macro which makes an argument vector without parsing it.
*
* arg is the unparsed right-hand side of the equals sign.
* buff3 is an unparsed version of the argument to the command.
* unp is the full unparsed command.
*/
/* now scan all the commands */
switch (command[0]) {
case '@':
switch (command[1]) {
case '@':
/* dummy statement, '@@' is the comment signal.
* since it's a comment, just ignore it.
*/
break;
case 'a':
case 'A':
if(!strcasecmp(command,"@allhalt")) {
do_allhalt(player);
break;
}
switch(command[2]) {
#ifdef QUOTA
case 'l':
case 'L':
Matched("@allquota");
do_allquota(player, arg1);
break;
#endif /* QUOTA */
case 't':
case 'T':
if(string_prefix("@atrlock", command)) {
do_atrlock(player, arg1, arg2);
} else {
Matched("@atrchown");
do_atrchown(player, arg1, arg2);
}
break;
default:
goto bad;
}
break;
case 'b':
case 'B':
Matched("@boot");
if (!slashp)
do_boot(player, arg1, 0);
else IfSwitch("port")
do_boot(player, arg1, 1);
else
goto bad;
break;
case 'c':
case 'C':
/* chown, create */
switch (command[2]) {
case 'h':
case 'H':
switch (command[3]) {
#if (CHAT_SYSTEM >= 2)
case 'a':
case 'A':
if (gagged) break;
switch(command[4]) {
case 'n':
case 'N':
Matched("@channel");
if (!slashp)
do_channel(player, arg1, arg2);
else IfSwitch("who")
do_channel(player, arg1, "who");
else IfSwitch("wipe")
do_channel(player, arg1, "wipe");
else IfSwitch("on")
do_channel(player, arg1, "on");
else IfSwitch("off")
do_channel(player, arg1, "off");
else IfSwitch("list")
do_channel_list(player);
else IfSwitch("add")
do_chan_admin(player, arg1, arg2, 0);
else IfSwitch("delete")
do_chan_admin(player, arg1, arg2, 1);
else IfSwitch("name")
do_chan_admin(player, arg1, arg2, 2);
else IfSwitch("priv")
do_chan_admin(player, arg1, arg2, 3);
else
goto bad;
break;
case 't':
case 'T':
Matched("@chat");
do_chat(player, find_channel(arg1), arg2);
break;
default:
goto bad;
} /* command[4] */
break; /* case command[3] == 'a' */
#endif /* CHAT_SYSTEM */
case 'o':
case 'O':
if(!strcasecmp(command,"@chownall")) {
do_chownall(player, arg1, arg2);
break;
} else {
if (gagged) break;
Matched("@chown");
do_chown(player, arg1, arg2);
break;
}
case 'z':
case 'Z':
if (!strcasecmp(command, "@chzoneall")) {
do_chzoneall(player, arg1, arg2);
break;
} else {
if (gagged) break;
Matched("@chzone");
do_chzone(player, arg1, arg2);
break;
}
}
break;
case 'o':
case 'O':
Matched("@config");
if (!slashp)
do_config(player, 0);
else IfSwitch("globals")
do_config(player, 1);
else IfSwitch("defaults")
do_config(player, 0);
else IfSwitch("costs")
do_config(player, 2);
else IfSwitch("functions")
do_list_functions(player);
else
goto bad;
break;
case 'p':
case 'P':
Matched("@cpattr");
do_cpattr(player, arg1, argv);
break;
case 'r':
case 'R':
if (gagged)
break;
Matched("@create");
do_create(player, arg1, atol(arg2));
break;
case 'l':
case 'L':
if (gagged)
break;
Matched("@clone");
do_clone(player, arg1);
break;
default:
goto bad;
}
break;
case 'd':
case 'D':
/* daytime, dbck, dig, or dump */
switch (command[2]) {
#ifdef DESTROY
case 'b':
case 'B':
Matched("@dbck");
do_dbck(player);
break;
#endif
case 'E':
case 'e':
switch (command[3]) {
case 'c':
case 'C':
Matched("@decompile");
do_decompile(player, arg1);
break;
#ifdef DESTROY
case 's':
case 'S':
Matched("@destroy");
if (!slashp)
do_destroy(player, arg1, 0);
else IfSwitch("override")
do_destroy(player, arg1, 1);
else
goto bad;
break;
#endif /* DESTROY */
default:
goto bad;
}
break;
case 'i':
case 'I':
switch (command[3]) {
case 'g':
case 'G':
if (gagged)
break;
Matched("@dig");
if (!slashp)
do_dig(player, arg1, argv, 0);
else IfSwitch("teleport")
do_dig(player, arg1, argv, 1);
else
goto bad;
break;
case 's':
case 'S':
Matched("@disable");
do_enable(player, arg1, 0);
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
switch (command[3]) {
#ifdef AT_DOING
case 'i':
case 'I':
if(gagged)
break;
if(Typeof(player) != TYPE_PLAYER)
break;
Matched("@doing");
if (!slashp)
do_doing(player, buff3);
else IfSwitch("header")
do_poll(player, buff3);
else
goto bad;
break;
#endif
case 'l':
case 'L':
Matched("@dolist");
do_dolist(player, arg1, arg, cause, 0);
break;
default:
goto bad;
}
break;
case 'r':
case 'R':
Matched("@drain");
do_notify(player, cause, 2, arg1, arg2);
break;
case 'u':
case 'U':
Matched("@dump");
if (!slashp)
do_dump(player, "", 0);
else IfSwitch("paranoid")
do_dump(player, arg1, 1);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'E':
case 'e':
switch (command[2]) {
case 'd':
case 'D':
if (gagged)
break;
Matched("@edit");
do_gedit(player, arg1, vargs);
break;
case 'l':
case 'L':
if (gagged) break;
Matched("@elock");
do_lock(player, arg1, arg2, ENTERLOCK);
break;
case 'm':
case 'M':
if (gagged)
break;
Matched("@emit");
if (!slashp)
do_emit(player, argu);
else IfSwitch("room")
do_lemit(player, argu);
else
goto bad;
break;
case 'n':
case 'N':
if(gagged) break;
switch (command[3]) {
case 'a':
case 'A':
Matched("@enable");
do_enable(player, arg1, 1);
break;
case 't':
case 'T':
Matched("@entrances");
if (!slashp)
do_entrances(player, arg1, argv, 0);
else IfSwitch("exits")
do_entrances(player, arg1, argv, 1);
else IfSwitch("things")
do_entrances(player, arg1, argv, 2);
else IfSwitch("players")
do_entrances(player, arg1, argv, 3);
else IfSwitch("rooms")
do_entrances(player, arg1, argv, 4);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'u':
case 'U':
if (gagged) break;
Matched("@eunlock");
do_unlock(player, arg1, ENTERLOCK);
break;
default:
goto bad;
}
break;
case 'F':
case 'f':
/* find, or force */
switch (command[2]) {
case 'i':
case 'I':
switch (command[3]) {
case 'n':
case 'N':
if (gagged)
break;
Matched("@find");
do_find(player, arg1, argv);
break;
case 'x':
case 'X':
Matched("@fixdb");
if (!slashp)
goto bad;
else IfSwitch("location")
do_fixdb(player, arg1, arg2, 0);
else IfSwitch("contents")
do_fixdb(player, arg1, arg2, 1);
else IfSwitch("exits")
do_fixdb(player, arg1, arg2, 2);
else IfSwitch("next")
do_fixdb(player, arg1, arg2, 3);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
if (gagged)
break;
Matched("@force");
do_force(player, arg1, arg2);
break;
case 'u':
case 'U':
if (gagged)
break;
Matched("@function");
do_function(player, arg1, argv);
break;
default:
goto bad;
}
break;
case 'g':
case 'G':
if(gagged)
break;
switch (command[2]) {
case 'e':
case 'E':
Matched("@gedit");
do_gedit(player, arg1, vargs);
break;
case 'r':
case 'R':
Matched("@grep");
if (!slashp)
do_grep(player, arg1, arg, 0);
else IfSwitch("list")
do_grep(player, arg1, arg, 0);
else IfSwitch("print")
do_grep(player, arg1, arg, 1);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
switch (command[2]) {
case 'a':
case 'A':
/* halt */
Matched("@halt");
if (!slashp)
do_halt1(player, arg1, arg2);
else IfSwitch("all")
do_allhalt(player);
else
goto bad;
break;
case 'i':
case 'I':
Matched("@hide");
if (!slashp)
hide_player(player, 1);
else IfSwitch("no")
hide_player(player, 0);
else IfSwitch("yes")
hide_player(player, 1);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'k':
case 'K':
Matched("@kick");
do_kick(player, arg1);
break;
case 'l':
case 'L':
/* lock or link */
switch (command[2]) {
case 'e':
case 'E':
if(gagged) break;
Matched ("@lemit");
do_lemit(player,arg1,arg2);
break;
case 'i':
case 'I':
if(gagged) break;
if(string_prefix("@link", command)) {
do_link(player, arg1, arg2);
break;
} else {
Matched("@listmotd");
do_motd(player, 3, "");
break;
}
case 'o':
case 'O':
if (gagged) break;
Matched("@lock");
if (!slashp)
do_lock(player, arg1, arg2, BASICLOCK);
else IfSwitch("enter")
do_lock(player, arg1, arg2, ENTERLOCK);
else IfSwitch("tport")
do_lock(player, arg1, arg2, ENTERLOCK);
else IfSwitch("page")
do_lock(player, arg1, arg2, USELOCK);
else IfSwitch("use")
do_lock(player, arg1, arg2, USELOCK);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'm':
case 'M':
/* @mail, @map, @motd */
switch (command[2]) {
case 'a':
case 'A':
switch (command[3]) {
case 'i':
case 'I':
#ifdef USE_MAILER
if(gagged) break;
Matched("@mail");
if (!slashp)
do_mail(player, arg1, arg2);
else IfSwitch("stats")
do_mail_stats(player, arg1, 0);
else IfSwitch("dstats")
do_mail_stats(player, arg1, 1);
else IfSwitch("fstats")
do_mail_stats(player, arg1, 2);
else IfSwitch("debug")
do_mail_debug(player, arg1, arg2);
else
goto bad;
break;
#endif
case 'p':
case 'P':
Matched("@map");
do_dolist(player, arg1, arg, cause, 1);
break;
default:
goto bad;
}
break;
case 'o':
case 'O':
if (gagged) break;
Matched("@motd");
if (!slashp)
do_motd(player, 1, argu);
else IfSwitch("connect")
do_motd(player, 1, argu);
else IfSwitch("list")
do_motd(player, 3, "");
else IfSwitch("wizard")
do_motd(player, 2, argu);
else IfSwitch("down")
do_motd(player, 4, argu);
else IfSwitch("full")
do_motd(player, 5, argu);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'n':
case 'N':
/* @name, @newpassword */
switch (command[2]) {
case 'a':
case 'A':
if (gagged)
break;
Matched("@name");
do_name(player, arg1, arg2);
break;
case 'e':
case 'E':
if (strcmp(command, "@newpassword"))
goto bad;
do_newpassword(player, arg1, arg2);
break;
case 'o':
case 'O':
Matched("@notify");
if (!slashp)
do_notify(player, cause, 0, arg1, arg2);
else IfSwitch("all")
do_notify(player, cause, 1, arg1, arg2);
else
goto bad;
break;
#ifdef DESTROY
case 'u':
case 'U':
if (gagged) break;
Matched("@nuke");
do_destroy(player, arg1, 1);
break;
#endif
default:
goto bad;
}
break;
case 'o':
case 'O':
/* @oemit, @open */
switch (command[2]) {
case 'e':
case 'E':
if (gagged)
break;
Matched("@oemit");
do_oemit(player, arg1, arg2);
break;
case 'p':
case 'P':
if (gagged)
break;
Matched("@open");
do_open(player, arg1, argv);
break;
default:
goto bad;
}
break;
case 'p':
case 'P':
switch (command[2]) {
case 'a':
case 'A':
switch (command[3]) {
case 'r':
case 'R':
Matched("@parent");
do_parent(player, arg1, arg2);
break;
case 's':
case 'S':
Matched("@password");
do_password(player, arg1, arg2);
break;
default:
goto bad;
}
break;
#ifdef WCREAT
case 'C':
case 'c':
Matched("@pcreate");
do_pcreate(player, arg1, arg2);
break;
#endif
case 'E':
case 'e':
if (gagged)
break;
Matched("@pemit");
if (!slashp)
#ifdef SILENT_PEMIT
do_pemit(player, arg1, arg2, 1);
#else
do_pemit(player, arg1, arg2, 0);
#endif /* SILENT_PEMIT */
else IfSwitch("noisy")
do_pemit(player, arg1, arg2, 0);
else IfSwitch("silent")
do_pemit(player, arg1, arg2, 1);
else IfSwitch("contents")
do_remit(player, arg1, arg2);
else
goto bad;
break;
case 'O':
case 'o':
switch (command[3]) {
#ifdef AT_DOING
case 'l':
case 'L':
Matched("@poll");
do_poll(player, argu);
break;
#endif /* AT_DOING */
case 'o':
case 'O':
if (strcmp(command, "@poor"))
goto bad;
do_poor(player, arg1);
break;
case 'w':
case 'W':
Matched("@power");
do_power(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'S':
case 's':
Matched("@ps");
if (!slashp)
do_queue(player, arg1);
else IfSwitch("all")
do_queue(player, "all");
else IfSwitch("summary")
do_queue(player, "count");
else
goto bad;
break;
#ifdef DESTROY
case 'u':
case 'U':
Matched("@purge");
do_purge(player);
break;
#endif /* DESTROY */
default:
goto bad;
}
break;
#ifdef QUOTA
case 'q':
case 'Q':
Matched("@quota");
if (!slashp)
do_quota(player, arg1, "", 0);
else IfSwitch("all")
do_allquota(player, arg1);
else IfSwitch("set")
do_quota(player, arg1, arg2, 1);
else
goto bad;
break;
#endif /* QUOTA */
case 'r':
case 'R':
switch (command[2]) {
case 'e':
case 'E':
if (gagged) break;
switch (command[3]) {
case 'a':
case 'A':
Matched("@readcache");
do_readcache(player);
break;
case 'm':
case 'M':
Matched("@remit");
do_remit(player, arg1, arg2);
break;
case 'j':
case 'J':
Matched("@rejectmotd");
do_motd(player, 4, argu);
break;
default:
goto bad;
}
break;
#ifdef ROYALTY_FLAG
case 'w':
case 'W':
if (string_prefix("@rwall", command)) {
do_wall(player, argu, 1, 1);
} else if (string_prefix("@rwallpose", command)) {
do_wall(player, argu, 1, 2);
} else if (string_prefix("@rwallemit", command)) {
do_wall(player, argu, 1, 3);
} else
goto bad;
break;
#endif
default:
goto bad;
}
break;
case 's':
case 'S':
/* set, shutdown, success */
switch (command[2]) {
case 'c':
case 'C':
if (gagged)
break;
Matched("@scan");
if (!slashp)
do_scan(player, argu, CHECK_INVENTORY | CHECK_NEIGHBORS |
CHECK_SELF | CHECK_HERE | CHECK_ZONE | CHECK_GLOBAL);
else IfSwitch("room")
do_scan(player, argu, CHECK_NEIGHBORS | CHECK_HERE);
else IfSwitch("self")
do_scan(player, argu, CHECK_INVENTORY | CHECK_SELF);
else IfSwitch("zone")
do_scan(player, argu, CHECK_ZONE);
else IfSwitch("globals")
do_scan(player, argu, CHECK_GLOBAL);
else
goto bad;
break;
case 'e':
case 'E':
/* patched to add 'search' command */
switch (command[3]) {
case 'a':
case 'A':
Matched("@search");
do_search(player, arg1, vargs);
break;
case 'l':
case 'L':
Matched("@select");
do_switch(player, arg1, vargs, cause, 1);
break;
case 't':
case 'T':
if (gagged)
break;
Matched("@set");
do_set(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
if (strcmp(command, "@shutdown"))
goto bad;
do_shutdown(player);
break;
case 't':
case 'T':
Matched("@stats");
#ifdef DBSTATS_ENABLED
if (!slashp)
do_stats(player, arg1);
else IfSwitch("database")
do_dbstats(player);
else
goto bad;
#else
do_stats(player, arg1);
#endif /* DBSTATS_ENABLED */
break;
case 'w':
case 'W':
switch (command[3]) {
case 'e':
case 'E':
Matched("@sweep");
if (!slashp)
do_sweep(player, arg1);
else IfSwitch("connected")
do_sweep(player, "connected");
else IfSwitch("here")
do_sweep(player, "here");
else IfSwitch("inventory")
do_sweep(player, "inventory");
else IfSwitch("exits")
do_sweep(player, "exits");
else
goto bad;
break;
case 'i':
case 'I':
if (gagged)
break;
Matched("@switch");
if (!slashp)
do_switch(player, arg1, vargs, cause, 0);
else IfSwitch("first")
do_switch(player, arg1, vargs, cause, 1);
else IfSwitch("all")
do_switch(player, arg1, vargs, cause, 0);
else
goto bad;
break;
default:
goto bad;
}
break;
#ifdef QUOTA
case 'q':
case 'Q':
Matched("@squota");
do_quota(player, arg1, arg2, 1);
break;
#endif /* QUOTA */
default:
goto bad;
}
break;
case 't':
case 'T':
switch (command[2]) {
case 'e':
case 'E':
if (gagged)
break;
Matched("@teleport");
do_teleport(player, arg1, arg2);
break;
case 'r':
case 'R':
if (gagged)
break;
Matched("@trigger");
do_trigger(player, arg1, argv);
break;
case 'O':
case 'o':
if (strcmp(command, "@toad"))
goto bad;
do_toad(player, arg1);
break;
default:
goto bad;
}
break;
case 'u':
case 'U':
switch (command[2]) {
case 'l':
case 'L':
if (gagged) break;
Matched("@ulock");
do_lock(player, arg1, arg2, USELOCK);
break;
case 'n':
case 'N':
switch (command[4]) {
case 'i':
case 'I':
if (gagged) break;
Matched("@unlink");
do_unlink(player, arg1);
break;
case 'o':
case 'O':
if (gagged) break;
Matched("@unlock");
if (!slashp)
do_unlock(player, arg1, BASICLOCK);
else IfSwitch("enter")
do_unlock(player, arg1, ENTERLOCK);
else IfSwitch("tport")
do_unlock(player, arg1, ENTERLOCK);
else IfSwitch("page")
do_unlock(player, arg1, USELOCK);
else IfSwitch("use")
do_unlock(player, arg1, USELOCK);
else
goto bad;
break;
default:
goto bad;
}
break;
case 'p':
case 'P':
Matched("@uptime");
do_uptime(player);
break;
case 'u':
case 'U':
if (gagged) break;
Matched("@uunlock");
do_unlock(player, arg1, USELOCK);
break;
default:
goto bad;
}
break;
case 'v':
case 'V':
switch (command[4]) {
case 'b':
case 'B':
Matched("@verb");
do_verb(player, cause, arg1, argv);
break;
case 's':
case 'S':
Matched("@version");
do_version(player);
break;
default:
goto bad;
}
break;
case 'w':
case 'W':
switch (command[2]) {
case 'a':
case 'A':
if (string_prefix("@wait", command)) {
do_wait(player, cause, arg1, arg);
} else if (string_prefix("@wall", command)) {
Matched("@wall");
if (!slashp)
do_wall(player, argu, 2, 1);
else IfSwitch("wizard")
do_wall(player, argu, 0, 1);
else IfSwitch("royalty")
do_wall(player, argu, 1, 1);
else IfSwitch("emit")
do_wall(player, argu, 2, 3);
else IfSwitch("pose")
do_wall(player, argu, 2, 2);
else
goto bad;
} else if (string_prefix("@wallpose", command)) {
do_wall(player, argu, 2, 2);
} else if (string_prefix("@wallemit", command)) {
do_wall(player, argu, 2, 3);
} else
goto bad;
break;
#ifdef PLAYER_LOCATE
case 'h':
case 'H':
if (gagged)
break;
Matched("@whereis");
do_whereis(player, arg1);
break;
#endif /* PLAYER_LOCATE */
case 'i':
case 'I':
if (string_prefix("@wipe", command)) {
do_wipe(player, arg1);
} else if(string_prefix("@wizwall", command)) {
do_wall(player, argu, 0, 1);
} else if(string_prefix("@wizmotd", command)) {
do_motd(player, 2, argu);
} else if(string_prefix("@wizpose", command)) {
do_wall(player, argu, 0, 2);
} else if(string_prefix("@wizemit", command)) {
do_wall(player, argu, 0, 3);
} else
goto bad;
break;
default:
goto bad;
}
break;
case 'z':
case 'Z':
if (gagged) break;
Matched("@zemit");
do_zemit(player, arg1, arg2);
break;
default:
goto bad;
}
break;
case 'b':
case 'B':
Matched("brief");
do_examine(player, arg1, 1);
break;
case 'd':
case 'D':
if (!Mobile(player))
break;
Matched("drop");
do_drop(player, arg1);
break;
case 'e':
case 'E':
switch (command[1]) {
case 'X':
case 'x':
case '\0':
Matched("examine");
if (!slashp)
do_examine(player, arg1, 0);
else IfSwitch("brief")
do_examine(player, arg1, 1);
else IfSwitch("debug")
do_debug_examine(player, arg1);
else
goto bad;
break;
case 'N':
case 'n':
if(Typeof(player) == TYPE_EXIT || Typeof(player) == TYPE_ROOM)
break;
Matched("enter");
do_enter(player, arg1, 0);
break;
#ifdef EVENTS
case 'v':
case 'V':
Matched("events");
do_new_spitfile(player, buff3, EVENTINDX, EVENT_FILE);
break;
#endif
default:
goto bad;
}
break;
case 'g':
case 'G':
/* get, give, go, or gripe */
switch (command[1]) {
case 'e':
case 'E':
if(gagged || !Mobile(player))
break;
Matched("get");
do_get(player, arg1);
break;
case 'i':
case 'I':
if (gagged)
break;
Matched("give");
do_give(player, arg1, arg2);
break;
case 'o':
case 'O':
if(Typeof(player) == TYPE_EXIT || Typeof(player) == TYPE_ROOM)
break;
Matched("goto");
move_wrapper(player, arg1);
break;
default:
goto bad;
}
break;
case 'h':
case 'H':
Matched("help");
do_new_spitfile(player, buff3, HELPINDX, HELPTEXT);
break;
case 'i':
case 'I':
Matched("inventory");
do_inventory(player);
break;
case 'k':
case 'K':
if (gagged)
break;
Matched("kill");
do_kill(player, arg1, atol(arg2), 0);
break;
case 'l':
case 'L':
switch (command[1]) {
case '\0': /* patch allow 'l' command to do a look */
do_look_at(player, arg1, 0);
break;
case 'o':
case 'O':
Matched("look");
if (!slashp)
do_look_at(player, arg1, 0);
else IfSwitch("outside")
do_look_at(player, arg1, 1);
else
goto bad;
break;
case 'E':
case 'e':
if(Typeof(player) == TYPE_ROOM || Typeof(player) == TYPE_EXIT)
break;
Matched("leave");
do_leave(player);
break;
default:
goto bad;
}
break;
case 'm':
case 'M':
if (!Mobile(player))
break;
Matched("move");
move_wrapper(player, arg1);
break;
case 'n':
case 'N':
/* news */
if (strcasecmp(command, "news"))
goto bad;
do_new_spitfile(player, buff3, NEWSINDX, NEWS_FILE);
break;
case 'p':
case 'P':
if (gagged)
break;
Matched("page");
if (index(buff3, '=') == NULL)
do_page(player, argu, NULL);
else
do_page(player, arg1, arg2);
break;
case 'r':
case 'R':
switch (command[1]) {
#ifdef ROBBERS
case 'o':
case 'O':
Matched("rob");
do_rob(player, arg1);
break;
#endif /* ROBBERS */
#ifdef ALLOW_RPAGE
case 'p':
case 'P':
Matched("rpage");
if (!slashp)
do_rpage(player, arg1, arg2);
else IfSwitch("list")
do_rpage_list(player);
else IfSwitch("add")
do_rpage_add(player, arg1, arg2);
else IfSwitch("delete")
do_rpage_delete(player, arg1, arg2);
else
goto bad;
break;
#endif /* ALLOW_RPAGE */
default:
Matched("read"); /* undocumented alias for look at */
do_look_at(player, arg1, 0);
break;
}
break;
case 's':
case 'S':
/* say, "score" */
switch (command[1]) {
case 'a':
case 'A':
if (gagged)
break;
Matched("say");
do_say(player, argu);
break;
case 'c':
case 'C':
Matched("score");
do_score(player);
break;
case 'l':
case 'L':
Matched("slay");
do_kill(player, arg1, 0, 1);
break;
default:
goto bad;
}
break;
case 't':
case 'T':
switch (command[1]) {
case 'a':
case 'A':
if(gagged || !Mobile(player))
break;
Matched("take");
do_get(player, arg1);
break;
case 'h':
case 'H':
if (gagged)
break;
Matched("think");
do_think(player, argu);
break;
default:
goto bad;
}
break;
case 'w':
case 'W':
if (gagged)
break;
Matched("whisper");
do_whisper(player, arg1, arg2);
break;
case 'u':
case 'U':
if (gagged) break;
Matched("use");
do_use(player, arg1);
break;
default:
bad:
/* now we do function evaluation on the command line, since
* from now on we're going to be passing the entire thing
* on to whatever handler we're using.
*/
cptr = exec(player, cause, EV_EVAL | EV_FCHECK | EV_STRIP, unp);
a = 0;
if (!gagged && Mobile(player)) {
/* if the "player" is an exit or room, no need to do these checks */
/* try matching enter aliases */
if (Location(player) != NOTHING &&
(i = alias_list_check(db[Location(player)].contents,
cptr, "EALIAS")) != -1) {
sprintf(temp, "#%d", i);
do_enter(player, temp, 1);
goto done;
}
/* if that didn't work, try matching leave aliases */
if ((Typeof(Location(player)) != TYPE_ROOM) &&
(loc_alias_check(Location(player), cptr, "LALIAS"))) {
do_leave(player);
goto done;
}
/* try matching user defined functions before chopping */
/* try objects in the player's location, the location itself,
* and objects in the player's inventory.
*/
if (Location(player) != NOTHING) {
a += list_match(Contents(Location(player)));
if (Location(player) != player)
a += cmd_match(Location(player));
}
if (Location(player) != player)
a += list_match(Contents(player));
/* now do check on zones */
if ((!a) && (Zone(Location(player)) != NOTHING)) {
#ifdef DO_GLOBALS
if (Typeof(Zone(Location(player))) == TYPE_ROOM) {
/* zone of player's location is a parent room */
if (Location(player) != Zone(player)) {
/* check parent room exits */
if (remote_exit(Zone(Location(player)), cptr)) {
if (!Mobile(player))
goto done;
else {
do_move(player, cptr, 2);
goto done;
}
} else
/* check commands in the parent room if no exits
* can match more than one $command in parent room
*/
a += list_match(Contents(Zone(Location(player))));
} /* end of parent room check */
} else
#endif
/* try matching commands on area zone object if GLOBALS
* aren't in use or zone object isn't a room
*/
if ((!a) && (Zone(Location(player)) != NOTHING))
a += cmd_match(Zone(Location(player)));
} /* end of matching on zone of player's location */
/* if nothing matched with parent room/zone object, try
* matching zone commands on the player's personal zone
*/
if ((!a) && (Zone(player) != NOTHING) &&
(Zone(Location(player)) != Zone(player))) {
a += cmd_match(Zone(player));
} /* end of zone stuff */
#ifdef DO_GLOBALS
/* check global exits only if no other commands are matched */
if ((!a) && (Location(player) != MASTER_ROOM)) {
if (global_exit(player, cptr)) {
if (!Mobile(player))
goto done;
else {
do_move(player, cptr, 1);
goto done;
}
} else
/* global user-defined commands checked if all else fails.
* May match more than one command in the master room.
*/
a += list_match(Contents(MASTER_ROOM));
} /* end of master room check */
#endif
} /* end of special checks */
if(!a) {
notify(player, "Huh? (Type \"help\" for help.)");
if (options.log_huhs)
do_log(LT_HUH, player, 0, "%s", unp);
}
break;
}
}
/* command has been executed. Free up memory. */
done:
if (cptr)
free(cptr);
if (buf1) {
free(buf1);
#ifdef MEM_CHECK
del_check("exec.buff");
#endif
}
if (saveptr) { /* arg2 */
free(saveptr);
#ifdef MEM_CHECK
del_check("exec.buff");
#endif
}
for (a = 0; a < MAX_ARG; a++) { /* argv */
if (fargs[a]) {
free((char *) fargs[a]);
#ifdef MEM_CHECK
del_check("exec.buff");
#endif
fargs[a] = NULL;
}
}
/* Hmm. This is a possible fix for the %0 bug. (T'nor@SC's suggestion)
for (a = 0; a < 10; a++)
wptr[a] = NULL;
The problem with this is that it screws up multiple statements
associated with a single group of stack values, i.e:
@va object=$test *:@emit %0; say %0
*/
}
/* now undef everything that needs to be */
#undef Matched
#undef arg1
#undef arg2
#undef argu
#undef argv
#undef vargs
#undef list_match
#undef cmd_match
int check_alias(command, list)
const char *command;
const char *list;
{
/* check if a string matches part of a semi-colon separated list */
const char *p;
while (*list) {
for (p = command; (*p && DOWNCASE(*p) == DOWNCASE(*list)
&& *list != EXIT_DELIMITER);
p++, list++)
;
if (*p == '\0') {
while (isspace(*list))
list++;
if (*list == '\0' || *list == EXIT_DELIMITER)
return 1; /* word matched */
}
/* didn't match. check next word in list */
while (*list && *list++ != EXIT_DELIMITER)
;
while (isspace(*list))
list++;
}
/* reached the end of the list without matching anything */
return 0;
}
/* match a list of things */
int list_check(thing, player, type, end, str, just_match)
dbref thing, player;
char type, end;
char *str;
int just_match;
{
int match = 0;
while (thing != NOTHING) {
if (atr_comm_match(thing, player, type, end, str, just_match))
match = 1;
thing = db[thing].next;
}
return (match);
}
int alias_list_check(thing, command, type)
dbref thing;
const char *command;
char *type;
{
ATTR *a;
char alias[BUFFER_LEN];
while (thing != NOTHING) {
a = atr_get_noparent(thing, type);
if (a) {
strcpy(alias, uncompress(a -> value));
if (check_alias(command, alias) != 0)
return thing; /* matched an alias */
}
thing = db[thing].next;
}
return -1;
}
int loc_alias_check(loc, command, type)
dbref loc;
const char *command;
char *type;
{
ATTR *a;
char alias[BUFFER_LEN];
a = atr_get_noparent(loc, type);
if (a) {
strcpy(alias, uncompress(a -> value));
return (check_alias(command, alias));
} else
return 0;
}
int Hearer(thing)
dbref thing;
{
ALIST *ptr;
if (IS(thing, TYPE_PLAYER, PLAYER_CONNECT) || Puppet(thing))
return (1);
for (ptr = db[thing].list; ptr; ptr = AL_NEXT(ptr)) {
if(!AL_BAD(ptr) && !strcmp(AL_NAME(ptr), "LISTEN"))
return 1;
}
return (0);
}
int Commer(thing)
dbref thing;
{
ALIST *ptr;
for (ptr = db[thing].list; ptr; ptr = AL_NEXT(ptr)) {
if(!AL_BAD(ptr)) {
if(*AL_STR(ptr) == '$')
return (1);
}
}
return (0);
}
int Listener(thing)
dbref thing;
{
ALIST *ptr;
if (IS(thing, TYPE_THING, THING_LISTEN))
return (1);
for (ptr = db[thing].list; ptr; ptr = AL_NEXT(ptr)) {
if(!AL_BAD(ptr)) {
if(*AL_STR(ptr) == '^')
return (1);
}
}
return (0);
}
void do_poor(player, arg1)
dbref player;
char *arg1;
{
int amt = atoi(arg1);
dbref a;
if (!God(player)) {
notify(player, "Only God can cause financial ruin.");
return;
}
for (a = 0; a < db_top; a++)
if (Typeof(a) == TYPE_PLAYER)
s_Pennies(a, amt);
notify(player,
tprintf("The money supply of all players has been reset to %d %s.",
amt, MONIES));
do_log(LT_WIZ, player, NOTHING,
"** POOR done ** Money supply reset to %d %s.",
amt, MONIES);
fflush(wizlog_fp);
}
void do_version(player)
dbref player;
{
char buff[BUFFER_LEN];
notify(player, tprintf("You are connected to %s", MUDNAME));
strcpy(buff, ctime(&start_time));
buff[strlen(buff) - 1] = '\0'; /* eat the newline */
notify(player, tprintf("Last restarted: %s", buff));
notify(player, tprintf("%s", VERSION));
notify(player, tprintf("Build date: %s %s", __TIME__, __DATE__));
}
/* Bind occurences of '##' in "action" to "arg", then run "action" */
void bind_and_queue(player, cause, action, arg)
dbref player;
dbref cause;
char *action;
char *arg;
{
char *repl, *command;
repl = replace_string("##", arg, action);
command = strip_braces(repl);
if (repl)
free(repl);
#ifdef MEM_CHECK
del_check("replace_string.buff");
#endif
parse_que(player, command, cause);
if (command)
free(command);
#ifdef MEM_CHECK
del_check("strip_braces.buff");
#endif
}
void do_scan(player, command, flag)
dbref player;
char *command;
int flag;
{
/* scan for possible matches of user-def'ed commands */
#define ScanFind(p,x) \
(Can_Examine(p,x) && \
((num = atr_comm_match(x, p, '$', ':', command, 1)) != 0))
dbref thing;
int num;
if (!GoodObject(Location(player))) {
notify(player, "Sorry, you are in an invalid location.");
return;
}
if (!command || !*command) {
notify(player, "What command do you want to scan for?");
return;
}
if (flag & CHECK_NEIGHBORS) {
notify(player, "Matches on contents of this room:");
DOLIST(thing, db[Location(player)].contents) {
if (ScanFind(player, thing))
notify(player,
tprintf("%s [%d]", unparse_object(player, thing), num));
}
}
if (flag & CHECK_HERE) {
if (ScanFind(player, Location(player)))
notify(player, tprintf("Matched here: %s [%d]",
unparse_object(player, Location(player)), num));
}
if (flag & CHECK_INVENTORY) {
notify(player, "Matches on carried objects:");
DOLIST(thing, db[player].contents) {
if (ScanFind(player, thing))
notify(player, tprintf("%s [%d]",
unparse_object(player, thing), num));
}
}
if (flag & CHECK_SELF) {
if (ScanFind(player, player))
notify(player, tprintf("Matched self: %s [%d]",
unparse_object(player, player), num));
}
if (flag & CHECK_ZONE) {
/* zone checks */
if (Zone(Location(player)) != NOTHING) {
if (Typeof(Zone(Location(player))) == TYPE_ROOM) {
/* zone of player's location is a parent room */
if (Location(player) != Zone(player)) {
notify(player, "Matches on parent room of location:");
DOLIST(thing, db[Zone(Location(player))].contents) {
if (ScanFind(player, thing))
notify(player, tprintf("%s [%d]",
unparse_object(player, thing), num));
}
}
} else {
/* regular zone object */
if (ScanFind(player, Zone(Location(player))))
notify(player,
tprintf("Matched zone of location: %s [%d]",
unparse_object(player, Zone(Location(player))), num));
}
}
if ((Zone(player) != NOTHING) &&
(Zone(player) != Zone(Location(player)))) {
/* check the player's personal zone */
if (ScanFind(player, Zone(player)))
notify(player, tprintf("Matched personal zone: %s [%d]",
unparse_object(player, Zone(player)), num));
}
}
#ifdef DO_GLOBALS
if ((flag & CHECK_GLOBAL) &&
(Location(player) != MASTER_ROOM) &&
(Zone(Location(player)) != MASTER_ROOM) &&
(Zone(player) != MASTER_ROOM)) {
/* try Master Room stuff */
notify(player, "Matches on objects in the Master Room:");
DOLIST(thing, db[MASTER_ROOM].contents) {
if (ScanFind(player, thing))
notify(player, tprintf("%s [%d]",
unparse_object(player, thing), num));
}
}
#endif /* DO_GLOBALS */
}
void do_dolist(player, list, command, cause, flag)
dbref player, cause;
char *list, *command;
int flag; /* 0 for @dolist, 1 for @map */
{
char *curr, *objstring;
char outbuf[BUFFER_LEN];
char *ptr, *ebuf;
if (!list || !*list) {
notify(player, "What do you want to do with the list?");
return;
}
strcpy(outbuf, "");
curr = list;
while (curr && *curr) {
while (*curr == ' ')
curr++;
if (*curr) {
objstring = parse_to(&curr, ' ', EV_STRIP);
if (!flag) {
/* @dolist, queue command */
bind_and_queue(player, cause, command, objstring);
} else {
/* it's @map, add to the output list */
ebuf = replace_string("##", objstring, command);
ptr = exec(player, cause, EV_STRIP | EV_FCHECK, ebuf);
free(ebuf);
#ifdef MEM_CHECK
del_check("replace_string.buff");
#endif
if (!*outbuf)
strcpy(outbuf, ptr);
else if (strlen(outbuf) + strlen(ptr) < BUFFER_LEN)
sprintf(outbuf, "%s %s", outbuf, ptr);
free(ptr);
#ifdef MEM_CHECK
del_check("exec.buff");
#endif
}
}
}
if (flag) {
/* if we're doing a @map, copy the list to an attribute */
atr_add(player, "MAPLIST", outbuf, GOD, NOTHING);
notify(player, "Function mapped onto list.");
}
}
void do_uptime(player)
dbref player;
{
FILE *fp;
char c;
char tbuf1[100];
int i;
int pid, psize;
int sec, min;
#ifdef HAS_RUSAGE
struct rusage usage;
#endif /* HAS_RUSAGE */
/* calculate time until next dump */
min = options.dump_counter / 60;
sec = options.dump_counter % 60;
if (!Wizard(player)) {
notify(player,
tprintf("Time until next database save: %d minutes %d seconds.",
min, sec));
return;
}
fp = popen("uptime", "r");
/* just in case the system is screwy */
if (fp == NULL) {
notify(player, "Error -- cannot execute uptime.");
fprintf(stderr, "** ERROR ** popen for @uptime returned NULL.");
return;
}
/* print system uptime */
for (i = 0; (c = getc(fp)) != '\n'; i++)
tbuf1[i] = c;
tbuf1[i] = '\0';
pclose(fp);
notify(player, tbuf1);
/* do process stats */
pid = getpid();
psize = getpagesize();
notify(player, tprintf("\nProcess ID: %10d %10d bytes per page",
pid, psize));
#ifdef HAS_RUSAGE
getrusage(RUSAGE_SELF, &usage);
notify(player, tprintf("Time used: %10d user %10d sys",
usage.ru_utime.tv_sec, usage.ru_stime.tv_sec));
notify(player, tprintf("Max res mem: %10d pages %10d bytes",
usage.ru_maxrss, (usage.ru_maxrss * psize)));
notify(player, tprintf("Integral mem:%10d shared %10d private %10d stack",
usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss));
notify(player, tprintf("Page faults: %10d hard %10d soft %10d swapouts",
usage.ru_majflt, usage.ru_minflt, usage.ru_nswap));
notify(player, tprintf("Disk I/O: %10d reads %10d writes",
usage.ru_inblock, usage.ru_oublock));
notify(player, tprintf("Network I/O: %10d in %10d out",
usage.ru_msgrcv, usage.ru_msgsnd));
notify(player, tprintf("Context swi: %10d vol %10d forced",
usage.ru_nvcsw, usage.ru_nivcsw));
notify(player, tprintf("Signals: %10d", usage.ru_nsignals));
#endif /* HAS_RUSAGE */
notify(player, tprintf("The head of the object free list is #%d.",
first_free));
notify(player,
tprintf("Time until next database save: %d minutes %d seconds.",
min, sec));
}
void do_config(player, type)
dbref player;
int type;
{
if (type == 2) {
notify(player, "Building costs:");
notify(player, tprintf(" Object creation....%d", OBJECT_COST));
notify(player, tprintf(" Room creation......%d", ROOM_COST));
notify(player, tprintf(" Exit creation......%d", EXIT_COST));
notify(player, tprintf(" Linking............%d", LINK_COST));
notify(player, tprintf(" Queue deposit......%d", QUEUE_COST));
notify(player, tprintf(" Quota per object...%d", QUOTA_COST));
notify(player, "Command costs:");
notify(player, tprintf(" page...............%d", PAGE_COST));
notify(player, tprintf(" @find..............%d", FIND_COST));
notify(player, tprintf(" kill base cost.....%d", KILL_BASE_COST));
notify(player, tprintf(" kill minimum cost..%d", KILL_MIN_COST));
notify(player, tprintf(" kill insurance.....%d", KILL_BONUS));
return;
}
if (type == 1) {
notify(player, "Global parameters:");
notify(player, tprintf(" Logins............%s",
(options.login_allow) ? "enabled" : "disabled"));
notify(player, tprintf(" Daytime...........%s",
(options.daytime) ? "enabled" : "disabled"));
notify(player, tprintf(" Log commands......%s",
(options.log_commands) ? "enabled" : "disabled"));
notify(player, tprintf(" Log huhs..........%s",
(options.log_huhs) ? "enabled" : "disabled"));
notify(player, tprintf(" Log forces........%s",
(options.log_forces) ? "enabled" : "disabled"));
notify(player, tprintf(" Log wizwalls......%s",
(options.log_walls) ? "enabled" : "disabled"));
return;
}
#ifdef RESTRICTED_BUILDING
#ifdef FREE_OBJECTS
notify(player, "Players without a BUILDER bit can only create objects.");
#else
notify(player, "Players without a BUILDER bit cannot build anything.");
#endif
#else
notify(player, "Players do not need BUILDER bits to build.");
#endif
#ifdef QUOTA
notify(player, "Quota restrictions are in effect.");
#else
notify(player, "There are no quota restrictions.");
#endif /* QUOTA */
#ifdef BUILDING_LIMIT
notify(player, tprintf("There is a limit of %d objects.", DBTOP_MAX));
#else
notify(player, "There is no maximum database size.");
#endif /* BUILDING_LIMIT */
#ifdef USE_MAILER
notify(player, "The built-in MUSH mailing system is being used.");
#else
notify(player, "The built-in MUSH mailing system is not being used.");
#endif
#ifdef CONCENTRATOR
notify(player, "Concentrator is enabling large numbers of connections.");
#else
notify(player, "Concentrator is not enabled.");
#endif
#if (CHAT_SYSTEM >= 2)
notify(player, "The chat system is enabled.");
#else
notify(player, "The chat system is disabled.");
#endif
#ifdef LOCKOUT
notify(player, "Site lockout is enabled.");
#else
notify(player, "Site lockout is not enabled.");
#endif
#ifdef WCREAT
notify(player, "Player registration is in effect.");
#else
notify(player, "Player registration is not in effect.");
#endif
#ifdef FLAGS_ON_EXAMINE
notify(player, "Examine shows the expanded flag list.");
#else
notify(player, "Examine does not show the expanded flag list.");
#endif
#ifdef EX_PUBLIC_ATTRIBS
notify(player, "Examine shows public attributes.");
#else
notify(player, "Examine does not show public attributes.");
#endif
#ifdef TINY_ATTRS
notify(player, "Attributes are printed in TinyMUSH format.");
#else
notify(player, "Attributes are printed in expanded format.");
#endif
#ifdef FULL_INVIS
notify(player, "Dark players/objects show up as Someone/Something.");
#else
notify(player, "Dark players/objects are not totally anonymous.");
#endif
#ifdef PARANOID_NOSPOOF
notify(player, "Nospoof notification shows name and object number.");
#else
notify(player, "Nospoof notification shows the name of the object only.");
#endif
#ifdef PLAYER_LOCATE
notify(player, "The location of players not set UNFINDABLE can be found.");
#else
notify(player, "The location of players cannot be found.");
#endif
#ifdef PLAYER_LISTEN
notify(player, "Players can @listen.");
#else
notify(player, "Players cannot @listen.");
#endif
#ifdef FLOATING_POINTS
notify(player, "Floating point functions are enabled.");
#else
notify(player, "Floating point functions are not enabled.");
#endif
#ifdef AT_DOING
notify(player, "Doing polls are enabled.");
#else
notify(player, "Doing polls are not enabled.");
#endif
#ifdef GLOBAL_CONNECTS
#ifdef DO_GLOBALS
notify(player, "Zone/global aconnects and adisconnects are enabled.");
#else
notify(player, "Zone aconnects and adisconnects are enabled.");
#endif
#else
notify(player, "Zone/global aconnects and disconnects are disabled.");
#endif
#ifdef ROYALTY_FLAG
notify(player, "The ROYALTY flag is enabled.");
#else
notify(player, "The ROYALTY flag is disabled.");
#endif
#ifdef INHERIT_FLAG
notify(player, "The INHERIT flag is enabled.");
#else
notify(player, "The INHERIT flag is disabled.");
#endif
#ifdef NO_FORK
notify(player, "Forking is disabled. Game will freeze during dumps.");
#else
notify(player, "There should be no slowdown due to database saves.");
#endif
notify(player, tprintf("The database is being saved every %d minutes.",
(int) DUMP_INTERVAL / 60));
#ifdef RWHO_SEND
notify(player, tprintf("The RWHO server is %s", RWHOSERV));
#ifdef FULL_WHO
notify(player, "The MUSH is sending and receiving RWHO information.");
#else
notify(player, "The MUSH is sending RWHO information.");
#endif
#else
notify(player, "The MUSH is not connected to an RWHO server.");
#endif
#ifdef ALLOW_RPAGE
notify(player, "Remote-paging to other MUSHes is enabled.");
#else
notify(player, "Remote-paging to other MUSHes is disabled.");
#endif
notify(player, tprintf("The starting location of players is #%d.",
PLAYER_START));
#ifdef DO_GLOBALS
notify(player, tprintf("The master room is #%d.", MASTER_ROOM));
#else
notify(player, "There is no master room.");
#endif
#ifdef GUEST_RESTRICT
notify(player, tprintf("The guest player is #%d.", GUEST_PLAYER));
#else
notify(player, "There is no guest character.");
#endif
#ifdef IDLE_TIMEOUT
notify(player,
tprintf("The inactivity limit is %d minutes.", INACTIVITY_LIMIT));
#else
notify(player, "There is no inactivity timeout.");
#endif
#ifdef LOGIN_LIMIT
notify(player,
tprintf("The maximum number of logins is %d.", MAX_LOGINS));
#else
notify(player, "There is no maxmium number of logins.");
#endif
notify(player, tprintf("The maximum number of queued commands is %d.",
QUEUE_QUOTA));
}